package com.ldy.transmit.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
import java.util.Map.Entry;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ldy.transmit.filter.LdyHttpServletRequest;
import com.ldy.transmit.io.MultipartFileResource;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;

import com.alibaba.fastjson.JSONObject;

@RestController
@RequestMapping("/")
public class BaseController {
	
	protected Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
	protected RestTemplate restTemplate;
	
	protected JSONObject getForJSONObject(URI uri, HttpServletRequest request, Map<String , Object> uriVariables) {
		
        return exchangeForJSONObject(uri, HttpMethod.GET, request, uriVariables);
	}

	protected JSONObject getForJSONObject(String uri, HttpServletRequest request, Map<String , Object> uriVariables) {
		return exchangeForJSONObject(URI.create(uri), HttpMethod.GET, request, uriVariables);
	}
	protected JSONObject getForJSONObject(URI uri, HttpServletRequest request) {
		return getForJSONObject(uri, request, null);
	}
	protected JSONObject getForJSONObject(String uri, HttpServletRequest request) {
		return getForJSONObject(uri, request, null);
	}
	protected JSONObject postForJSONObject(URI uri, HttpServletRequest request) {
		return exchangeForJSONObject(uri, HttpMethod.POST, request, null);
	}
	protected JSONObject postForJSONObject(String uri, HttpServletRequest request) {
		return exchangeForJSONObject(URI.create(uri), HttpMethod.POST, request, null);
	}
	
	@SuppressWarnings("unchecked")
	private JSONObject exchangeForJSONObject(URI uri, HttpMethod method, HttpServletRequest request, Map<String , Object> uriVariables) {
		HttpHeaders requestHeaders = new HttpHeaders();
		Enumeration<String> headerNames = request.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String key = (String) headerNames.nextElement();
			String value = request.getHeader(key);
			requestHeaders.add(key, value);
		}
		
		
//		if(request.getContentType() != null) {
//			int sepaterIndex = request.getContentType().indexOf(";");
//			requestHeaders.setContentType(MediaType.valueOf(request.getContentType().substring(0, sepaterIndex>0?sepaterIndex:request.getContentType().length())));
//		}
		Cookie[] cookies = request.getCookies();
		List<String> coo = new ArrayList<>();
		if(cookies != null) {
			for (Cookie cookie : cookies) {
				coo.add(cookie.getName()+"="+cookie.getValue());
			}
		}
		if(!coo.isEmpty())
			requestHeaders.put("Cookie", coo);
//		if(HttpMethod.GET == method) {
//			requestHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
//			requestHeaders.setContentType(MediaType.APPLICATION_JSON);
//		}
		long currTime = System.currentTimeMillis();
		RequestEntity<?> requestEntity = null; 
		String queryString = request.getQueryString();
		if(StringUtils.isNotBlank(queryString)) {
			try {
				uri = uri.resolve(uri.toString()+"?" + URLDecoder.decode(queryString, "UTF-8"));
			} catch (UnsupportedEncodingException e) {
				uri = uri.resolve(uri.toString()+"?" + queryString);
			}
		}
		if(HttpMethod.GET == method) {
			requestEntity = new RequestEntity<>(requestHeaders, method, uri);
			if (uriVariables != null) {
				return restTemplate.exchange(uri.toString(), HttpMethod.GET, requestEntity, JSONObject.class, uriVariables).getBody();
			}
			String ressult = restTemplate.exchange(uri.toString(), HttpMethod.GET, requestEntity, String.class).getBody();
//			System.out.println(ressult);
			long lastTime = System.currentTimeMillis();
			System.out.println("===========mobile========消耗时间：===="+ (lastTime-currTime) +"ms");
			return (JSONObject)JSONObject.parse(ressult);
		}else if(HttpMethod.POST == method) {
			try {
				Map<String, String[]> parameterMap = request.getParameterMap();
				MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<String, Object>();
				for (Iterator<Entry<String, String[]>> iter = parameterMap.entrySet().iterator(); iter.hasNext();) {
					Entry<String, String[]> entry = iter.next();
					multiValueMap.put(entry.getKey(), Arrays.asList(entry.getValue()));
				}
				if(request instanceof DefaultMultipartHttpServletRequest) {
					Map<String, List<MultipartFile>> multipartFiles = ((DefaultMultipartHttpServletRequest)request).getMultiFileMap();
					if(multipartFiles != null && !multipartFiles.isEmpty()) {
						requestHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
						for (Iterator<Entry<String, List<MultipartFile>>> iter = multipartFiles.entrySet().iterator(); iter.hasNext();) {
							Entry<String, List<MultipartFile>> entry = iter.next();
							for (MultipartFile file : entry.getValue()) {
								multiValueMap.add(entry.getKey(), new MultipartFileResource(file));
							}
						}
					}
				}
				if(StringUtils.contains(request.getContentType(),MediaType.APPLICATION_JSON_VALUE)) {
					requestHeaders.setContentType(MediaType.valueOf(request.getContentType()));
					requestEntity = new RequestEntity<>(getJsonStrFromInputStream(request), requestHeaders, method, uri);
				}else {
					requestEntity = new RequestEntity<>(multiValueMap, requestHeaders, method, uri);
				}
				JSONObject ressult = restTemplate.postForEntity(uri, requestEntity, JSONObject.class).getBody();
				System.out.println(ressult);
				return ressult;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		requestEntity = new RequestEntity<>(requestHeaders, method, uri);
		return restTemplate.exchange(requestEntity, JSONObject.class).getBody();
	}
	
	@RequestMapping("/greatdoors")
	public JSONObject mapAll(HttpServletRequest request, HttpServletResponse response) {
		String destnition = request.getHeader(LdyHttpServletRequest.HEADER_DESTINATION_URL);
		
		RequestMethod method = RequestMethod.valueOf(request.getMethod());
		if(method == RequestMethod.GET) {
			return getForJSONObject(destnition, request);
		}
		return postForJSONObject(destnition, request);
	}
	
	/**
	 * 在请求路径中如果包含了/sfimimgload/的地址，那么就转发到这里进行处理
	 * @param request
	 * @param response
	 * @return
	 */
	@GetMapping("/sfimimgload")
	public void requestForFile(HttpServletRequest request, HttpServletResponse response) {
		String destnition = request.getHeader(LdyHttpServletRequest.HEADER_DESTINATION_URL);
			//image和audio，
			HttpHeaders requestHeaders = new HttpHeaders();
			Enumeration<String> headerNames = request.getHeaderNames();
			while (headerNames.hasMoreElements()) {
				String key = (String) headerNames.nextElement();
				String value = request.getHeader(key);
				requestHeaders.add(key, value);
			}
			
			Cookie[] cookies = request.getCookies();
			List<String> coo = new ArrayList<>();
			if(cookies != null) {
				for (Cookie cookie : cookies) {
					coo.add(cookie.getName()+"="+cookie.getValue());
				}
			}
			if(!coo.isEmpty())
				requestHeaders.put("Cookie", coo);
			String queryString = request.getQueryString();
			URI uri = URI.create(destnition);
			if(StringUtils.isNotBlank(queryString)) {
				try {
					uri = uri.resolve(uri.toString()+"?" + URLDecoder.decode(queryString, "UTF-8"));
				} catch (UnsupportedEncodingException e) {
					uri = uri.resolve(uri.toString()+"?" + queryString);
				}
			}
			RequestEntity<Object> requestEntity = new RequestEntity<>(requestHeaders, HttpMethod.GET, uri);
			ResponseEntity<Resource> responseEntity = restTemplate.exchange(requestEntity, Resource.class);
			InputStream inputStream = null;
			ServletOutputStream out = null;
			try {
				inputStream = responseEntity.getBody().getInputStream();
				response.setContentType("application/octet-stream");
				response.setContentLength(inputStream.available());
				response.setHeader("Transfer-Encoding", "trunked");
				//response.setHeader("Content-Type", "image/*");
				//add by 80002946 获取cookie内容
				List<String> coookies = responseEntity.getHeaders().get("Set-Cookie");
				Map<String,Object> cookieMap=new HashMap<>();
				for(String cookie:coookies){
					String[] split = cookie.split(";");
					if(split.length>0){
						String[] keyValue = split[0].split("=");
						if(keyValue.length>1){
							cookieMap.put(keyValue[0],keyValue[1]);
						}
					}
				}
				String fileName = (String) cookieMap.get("mobile-down-filename");
				if(fileName!=null){
					response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
				}
				out = response.getOutputStream();
	            int len = 0;
	            byte[] buffer = new byte[1024];
	            while((len=inputStream.read(buffer))>0){
	            	out.write(buffer, 0, len);
	            }
			} catch (IOException e) {
				e.printStackTrace();
			}finally {
				try {
					if(inputStream != null) {
							inputStream.close();
					}
					if(out !=null) {
						out.flush();
						out.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	
	private String getJsonStrFromInputStream(HttpServletRequest request) {
		BufferedReader br = null;
		StringBuilder sb = null;
		try {
			br = new BufferedReader(new InputStreamReader(
					request.getInputStream()));
			String line = null;
			sb = new StringBuilder();
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}
			return URLDecoder.decode(sb.toString(), "UTF-8");
		} catch (IOException e) {
			return "";
		}finally {
			try {
				br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}
}
